package com.ruijie.autotest.log.common.sql;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Objects;
import java.util.function.UnaryOperator;

import static java.lang.String.format;

public class SqlField {
	private final DataSource dataSource;

	private final String tableName;

	private final String fieldName;

	private final SqlType sqlType;

	public SqlField(DataSource dataSource, String tableName, String fieldName, SqlType sqlType) {
		this.dataSource = dataSource;
		this.tableName = tableName;
		this.fieldName = fieldName;
		this.sqlType = sqlType;
	}

	public boolean existsValue(String correspondingLogValue) throws SQLException {
		return countOccurrencesOf(correspondingLogValue) > 0;
	}

	public int countOccurrencesOf(String correspondingLogValue) throws SQLException {
		String sql = format("select count(*) from %s where %s = %s",
				tableName, fieldName, type().represent(correspondingLogValue));
		System.out.println("sql = " + sql);
		try (Connection connection = dataSource.getConnection();
		     Statement statement = connection.createStatement();
		     ResultSet set = statement.executeQuery(sql)) {
			// get count result
			set.next();
			return set.getInt(1);
		}
	}

	public int countOccurrencesOf(String correspondingLogValue, UnaryOperator<String> mapper) throws SQLException {
		try (Connection connection = dataSource.getConnection();
		     Statement statement = connection.createStatement();
		     ResultSet rows = statement.executeQuery(format("select %s from %s", fieldName, tableName))) {
			int result = 0;
			while (rows.next()) {
				String mapped = mapper.apply(type().valueFrom(rows));
				if (Objects.equals(mapped, correspondingLogValue)) {
					result++;
				}
			}
			return result;
		}
	}

	public SqlType type() {
		return sqlType;
	}

	public String fieldName() {
		return fieldName;
	}

	@Override
	public String toString() {
		return "SqlFieldLocation{" +
				"dataSource=" + dataSource +
				", tableName='" + tableName + '\'' +
				", fieldName='" + fieldName + '\'' +
				", sqlType=" + sqlType +
				'}';
	}

	public static SqlField createSqlField(DataSource dataSource, String pattern) {
		String[] location = pattern.split("\\.");
		SqlTable table = new SqlTable(dataSource, location[0]);
		return table.columnFieldOf(location[1]);
	}
}
